// This MFC Samples source code demonstrates using MFC Microsoft Office Fluent User Interface 
// (the "Fluent UI") and is provided only as referential material to supplement the 
// Microsoft Foundation Classes Reference and related electronic documentation 
// included with the MFC C++ library software.  
// License terms to copy, use or distribute the Fluent UI are available separately.  
// To learn more about our Fluent UI licensing program, please visit 
// http://msdn.microsoft.com/officeui.
//
// Copyright (C) Microsoft Corporation
// All rights reserved.

// ChildFrm.cpp : implementation of the CChildFrame class
//

#include "stdafx.h"
#include "CookieTerm.h"
#include "BbsConsole.h"
#include "ChildFrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CChildFrame

IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWndEx)

BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWndEx)
	ON_COMMAND(ID_FILE_CLOSE, &CChildFrame::OnFileClose)
	ON_WM_SETFOCUS()
	ON_WM_CREATE()
	ON_WM_CLOSE()
	ON_WM_DESTROY()
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

// CChildFrame construction/destruction

CChildFrame::CChildFrame()
{
	// TODO: add member initialization code here
}

CChildFrame::~CChildFrame()
{
}


BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying the CREATESTRUCT cs
	if( !CMDIChildWndEx::PreCreateWindow(cs) )
		return FALSE;

	cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
	cs.lpszClass = AfxRegisterWndClass(0);
	return TRUE;
}

// CChildFrame diagnostics

#ifdef _DEBUG
void CChildFrame::AssertValid() const
{
	CMDIChildWndEx::AssertValid();
}

void CChildFrame::Dump(CDumpContext& dc) const
{
	CMDIChildWndEx::Dump(dc);
}
#endif //_DEBUG

// CChildFrame message handlers
void CChildFrame::OnFileClose() 
{
	// To close the frame, just send a WM_CLOSE, which is the equivalent
	// choosing close from the system menu.
	SendMessage(WM_CLOSE);
}

int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CMDIChildWndEx::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// create a view to occupy the client area of the frame
	if (!this->bbsConsole.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, 
		CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
	{
		TRACE0("Failed to create view window\n");
		return -1;
	}

	__hook(&CAnsiInterpreter::OnTextReceived, &this->ansiInterpreter, &CChildFrame::OnTextReceived);
	__hook(&CAnsiInterpreter::OnAnsiCommandReceived, &this->ansiInterpreter, &CChildFrame::OnAnsiCommandReceived);
	__hook(&CBbsConsole::OnInputReceivedEvent, &this->bbsConsole, &CChildFrame::OnInputReceivedFromConsole);
	__hook(&CTelnetShell::OnDataAvailableEvent, &this->shell, &CChildFrame::OnDataAvailableFromShell);
	__hook(&CTelnetShell::OnConnectEvent, &this->shell, &CChildFrame::OnConnectFromShell);
	__hook(&CTelnetShell::OnDisconnectEvent, &this->shell, &CChildFrame::OnDisconnectFromShell);

	DisplayAnsiFile(IDA_LOGO);

	this->bbsConsole.Reset();
	this->shell.SetHostname(_T("localhost"));
	this->shell.SetPort(23);
	this->shell.Connect();

	return 0;
}

void CChildFrame::OnSetFocus(CWnd* pOldWnd) 
{
	CMDIChildWndEx::OnSetFocus(pOldWnd);

	this->bbsConsole.SetFocus();
}

BOOL CChildFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) 
{
	// let the view have first crack at the command
	if (this->bbsConsole.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;
	
	// otherwise, do default handling
	return CMDIChildWndEx::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}


void CChildFrame::OnClose()
{
	if (this->shell.IsConnected())
	{
		if (IDYES == AfxMessageBox(_T("Sure you want to close?"), MB_YESNO))
			this->shell.Disconnect();
	}
	else
	{
		CWnd::OnClose();
	}
}

void CChildFrame::OnDestroy()
{
	__unhook(&CAnsiInterpreter::OnTextReceived, &this->ansiInterpreter, &CChildFrame::OnTextReceived);
	__unhook(&CAnsiInterpreter::OnAnsiCommandReceived, &this->ansiInterpreter, &CChildFrame::OnAnsiCommandReceived);
	__unhook(&CBbsConsole::OnInputReceivedEvent, &this->bbsConsole, &CChildFrame::OnInputReceivedFromConsole);
	__unhook(&CTelnetShell::OnDataAvailableEvent, &this->shell, &CChildFrame::OnDataAvailableFromShell);
	__unhook(&CTelnetShell::OnConnectEvent, &this->shell, &CChildFrame::OnConnectFromShell);
	__unhook(&CTelnetShell::OnDisconnectEvent, &this->shell, &CChildFrame::OnDisconnectFromShell);

	CMDIChildWndEx::OnDestroy();
}

void CChildFrame::OnAnsiCommandReceived (CAnsiCommand* command)
{
	this->bbsConsole.SendMessage(WM_ANSICOMMAND, 0, (LPARAM) command);
}

void CChildFrame::OnTextReceived (unsigned char* payloadBuffer, int payloadCount)
{
	this->bbsConsole.SendMessage(WM_TEXTRECEIVED, (WPARAM) payloadCount, (LPARAM) payloadBuffer);
}

void CChildFrame::OnDataAvailableFromShell(unsigned char* dataBuffer, int dataCount)
{
	this->ansiInterpreter.ProcessInput(dataBuffer, dataCount);
}

void CChildFrame::OnConnectFromShell(int nErrorCode)
{
	if (nErrorCode == 0)
	{
		this->bbsConsole.Reset();
	}
	else
	{
		AfxMessageBox(_T("Failed to connect"));
		this->shell.Disconnect();
	}
}

void CChildFrame::OnDisconnectFromShell()
{
	PostMessage(WM_CLOSE);
}

void CChildFrame::OnInputReceivedFromConsole(unsigned char* dataBuffer, int dataCount)
{
	if (!this->shell.IsConnected() || dataCount != this->shell.Send(dataBuffer, dataCount))
	{
		AfxMessageBox(_T("Error sending data"));
		PostMessage(WM_CLOSE);
	}
	delete[] dataBuffer;
}

void CChildFrame::DisplayAnsiFile(UINT id)
{
	HMODULE hModule = GetModuleHandle(NULL);
	HRSRC hRC = FindResource(hModule, MAKEINTRESOURCE(id), _T("ANSI"));
	HGLOBAL hGlobal=LoadResource(hModule,hRC);

	if(NULL != hGlobal) 
	{ 
        unsigned char* ansiBuffer = (unsigned char*) LockResource(hGlobal);
        unsigned int size = SizeofResource(hModule,hRC); 
		this->ansiInterpreter.ProcessInput(ansiBuffer, size);
	}
}

void CChildFrame::OnSize(UINT nType, int cx, int cy)
{
	CMDIChildWndEx::OnSize(nType, cx, cy);

	CRect clientRect;
	GetClientRect(clientRect);

	CSize childSize;
	this->bbsConsole.GetPreferredWindowSize(childSize);

	CSize diff = clientRect.Size() - childSize;
	this->bbsConsole.SetWindowPos(&wndTop, diff.cx/2, diff.cy/2, childSize.cx, childSize.cy, 0);
}

BOOL CChildFrame::OnEraseBkgnd(CDC* pDC)
{
	// TODO: Add your message handler code here and/or call default
	RECT rect;
	GetClientRect(&rect);
	pDC->FillSolidRect(&rect, RGB(100,10,10));

	return CMDIChildWndEx::OnEraseBkgnd(pDC);
}
